﻿/*
 * @author: wizardc
 */

using System.Collections.Generic;

namespace Dou.Pathfinding
{
    /// <summary>
    /// 基于图的寻路节点描述
    /// </summary>
    public class DijkstraMap
    {
        protected Dictionary<string, DijkstraNode> _map = new Dictionary<string, DijkstraNode>();
        protected List<DijkstraNode> _list = new List<DijkstraNode>();
        protected DijkstraNode _startNode;
        protected DijkstraNode _endNode;

        public List<DijkstraNode> List => _list;

        public int size => _list.Count;

        public DijkstraNode StartNode
        {
            get => _startNode;
            set => _startNode = value;
        }

        public DijkstraNode EndNode
        {
            get => _endNode;
            set => _endNode = value;
        }

        /// <summary>
        /// 设定节点之间的连接信息
        /// - 2 个节点之间的消耗 cost 不能为负数；
        /// - 2 个节点之间的连接是单向的，如果需要双向连接请调用 2 次设置连接方法 `SetNodeLink(a, b, 1);SetNodeLink(b, a, 1);`；
        /// </summary>
        public void SetNodeLink(string start, string end, float cost)
        {
            AddNode(start);
            var startNode = _map[start];
            AddNode(end);
            var endNode = _map[end];
            if (startNode.link.ContainsKey(endNode.name))
            {
                startNode.link[endNode.name].cost = cost;
            } else
            {
                var link = new DijkstraLink
                {
                    node = endNode,
                    cost = cost
                };
                startNode.link[endNode.name] = link;
            }
        }

        private void AddNode(string name)
        {
            if (!_map.ContainsKey(name))
            {
                var node = new DijkstraNode
                {
                    name = name
                };
                _map.Add(name, node);
                _list.Add(node);
            }
        }

        public DijkstraNode GetNode(string name)
        {
            if (_map.ContainsKey(name))
            {
                return _map[name];
            }

            return null;
        }

        public void SetStartNode(string name)
        {
            _startNode = _map[name];
        }

        public void SetEndNode(string name)
        {
            _endNode = _map[name];
        }
    }

    public class DijkstraNode
    {
        public string name;
        public Dictionary<string, DijkstraLink> link = new Dictionary<string, DijkstraLink>();
    }

    public class DijkstraLink
    {
        public DijkstraNode node;
        public float cost;
    }
}
